package com.gitee.wsl.mathematics.geometry.d2.triangle.ext

import com.gitee.wsl.mathematics.coordinate.d2.Coordinate2
import com.gitee.wsl.mathematics.geometry.d2.line.EdgeDistancePack
import com.gitee.wsl.mathematics.geometry.d2.line.LineShape2d
import com.gitee.wsl.mathematics.geometry.d2.line.ext.computeClosestPoint
import com.gitee.wsl.mathematics.geometry.d2.triangle.TriangleShape2d
import com.gitee.wsl.mathematics.vector.ext.minus


/**
 * Returns true if this triangle contains the given edge.
 *
 * @param edge
 * The edge to be tested
 * @return Returns true if this triangle contains the edge
 */
fun<T:Number> TriangleShape2d<T, *>.isNeighbour(edge: LineShape2d<T, *>): Boolean {
    return (a === edge.a || b === edge.a || c === edge.a) && (a === edge.b || b === edge.b || c === edge.b)
}

/**
 * Returns the vertex of this triangle that is not part of the given edge.
 *
 * @param edge
 * The edge
 * @return The vertex of this triangle that is not part of the edge
 */
fun<T:Number,V:Coordinate2<T,V>> TriangleShape2d<T, V>.getNoneEdgeVertex(edge: LineShape2d<T, *>): V? {
    /*if (a !== edge.a && a !== edge.b) {
        return a
    } else if (b !== edge.a && b !== edge.b) {
        return b
    } else if (c !== edge.a && c !== edge.b) {
        return c
    }
    return null*/

    return when{
        (a !== edge.a && a !== edge.b)-> a
        (b !== edge.a && b !== edge.b)-> b
        (c !== edge.a && c !== edge.b)-> c
        else -> null
    }
}

/**
 * Returns an EdgeDistancePack containing the edge and its distance nearest
 * to the specified point.
 *
 * @param point
 * The point the nearest edge is queried for
 * @return The edge of this triangle that is nearest to the specified point
 */
fun<T:Number,V:Coordinate2<T,V>,L:LineShape2d<T, V>> TriangleShape2d<T, V>.findNearestEdge(point:Coordinate2<T,*>): EdgeDistancePack<T,L> {
    val edges = ArrayList<EdgeDistancePack<T,L>>(3)
    var line = ab as L
    edges[0] = EdgeDistancePack(
        line,
        (line.computeClosestPoint(point)-point).length
    )
    line = bc as L
    edges[1] = EdgeDistancePack(
        line,
        (line.computeClosestPoint(point)-point).length
    )
    line = ca as L
    edges[2] = EdgeDistancePack(
        line,
        (line.computeClosestPoint(point)-point).length
    )

    return edges.sortedWith{a,b-> a.compareTo(b) }[0]
}

